package com.xored.glance.ui.viewers.tree;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.viewers.TreeViewer;

import com.xored.glance.ui.controls.decor.Cell;
import com.xored.glance.ui.controls.tree.TreeCell;
import com.xored.glance.ui.controls.tree.UnknownTreeVisitor;
import com.xored.glance.ui.controls.tree.content.TreeContent;
import com.xored.glance.ui.controls.tree.content.TreeItemContent;
import com.xored.glance.ui.controls.tree.content.TreeNode;

public class TreeViewerContent extends TreeContent {

	private int columns;
	private TreeContentProvider cp;
	private TreeLabelProvider lp;

	private Map<ViewerCell, TreeItemContent> cellToContent = new HashMap<ViewerCell, TreeItemContent>();

	public TreeViewerContent(TreeViewer viewer) {
		columns = viewer.getTree().getColumnCount();
		if (columns == 0) {
			columns = 1;
		}
		cp = TreeContentProvider.create(viewer);
		lp = TreeLabelProvider.create(viewer);
	}

	@Override
	public TreeItemContent getContent(TreeCell cell) {
		Object data = cell.getTreeItem().getData();
		if (data != null) {
			ViewerCell vc = new ViewerCell(data, cell.getColumn());
			return cellToContent.get(vc);
		}
		return null;
	}

	@Override
	public void index(IProgressMonitor monitor) {
		new TreeViewerVisitor(cp).visit(monitor);
	}

	class TreeViewerVisitor extends UnknownTreeVisitor {

		private TreeContentProvider provider;

		public TreeViewerVisitor(TreeContentProvider provider) {
			this.provider = provider;
		}

		@Override
		protected Object[] getRoots() {
			Object[] elements = provider.getRoots();
			return createNodes(TreeViewerContent.this, elements);
		}

		@Override
		protected Object[] getChildren(Object element) {
			Object[] elements = provider
					.getElements(nodeToElement.get(element));
			return createNodes((TreeNode) element, elements);
		}

		private TreeNode[] createNodes(TreeNode parent, Object[] elements) {
			TreeNode[] nodes = new TreeNode[elements.length];
			for (int i = 0; i < nodes.length; i++) {
				TreeNode node = new TreeNode();
				nodeToElement.put(node, elements[i]);
				for (int k = 0; k < columns; k++) {
					ViewerCell cell = new ViewerCell(elements[i], k);
					String text = lp.getText(elements[i], k);
					TreeItemContent item = new TreeItemContent(node, text, k);
					cellToContent.put(cell, item);
				}
				nodes[i] = node;
			}
			parent.add(nodes);
			return nodes;
		}

		private Map<TreeNode, Object> nodeToElement = new HashMap<TreeNode, Object>();

	}

	class ViewerCell extends Cell {

		private Object element;

		public ViewerCell(Object element, int column) {
			super(column);
			this.element = element;
		}

		@Override
		protected Object getElement() {
			return element;
		}

	}

}
